package com.zhoust.threadbatch.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.*;

/**
 * @author zhoust
 */
@EnableAsync
@Configuration
@Slf4j
public class ThreadPoolConfig {

    /**
     * 核心线程数（默认线程数）
     */
    @Value("${my-task.execution.pool.corePoolSize}")
    private int corePoolSize;
    /**
     * 最大线程数
     */
    @Value("${my-task.execution.pool.maxPoolSize}")
    private int maxPoolSize;
    /**
     * 允许线程空闲时间（单位：默认为秒）
     */
    @Value("${my-task.execution.pool.keepAliveTime}")
    private int keepAliveTime;
    /**
     * 缓冲队列大小
     */
    @Value("${my-task.execution.pool.queueCapacity}")
    private int queueCapacity;
    /**
     * 线程池名前缀
     */
    @Value("${my-task.execution.threadNamePrefix}")
    private String threadNamePrefix;
    /**
     * 拒绝策略 1. AbortPolicy 丢弃任务并抛异常，2. DiscardPolicy 丢弃任务不抛异常 3.DiscardOldestPolicy 丢弃队列最前面的线程（弃老）4.CallerRunsPolicy：由调用线程处理该任务
     */
    @Value("${my-task.execution.rejectedExecutionHandler}")
    private String rejectedExecutionHandler;
    /**
     * 是否回收核心线程
     */
    @Value("${my-task.execution.allowCoreThreadTimeOut}")
    private boolean allowCoreThreadTimeOut;
    /**
     * 执行完毕是否关闭线程池
     */
    @Value("${my-task.execution.waitForTasksToCompleteOnShutdown}")
    private boolean waitForTasksToCompleteOnShutdown;

    
    @Bean("asyncServiceThread")
    public Executor getThreadPool(){

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(getCorePoolSize(corePoolSize));
        // 队列允许等待的线程数
        executor.setQueueCapacity(queueCapacity);
        // 最大线程数，包含核心线程数
        executor.setMaxPoolSize(maxPoolSize);
        // 线程回收时间
        executor.setKeepAliveSeconds(keepAliveTime);
        // 4种拒绝策略 1. AbortPolicy 丢弃任务并抛异常，2. DiscardPolicy 丢弃任务不抛异常 3.DiscardOldestPolicy 丢弃队列最前面的线程（弃老）4.CallerRunsPolicy：由调用线程处理该任务
        executor.setRejectedExecutionHandler(getRejectedExecutionHandler(rejectedExecutionHandler));
        // 是否允许超时回收线程
        executor.setAllowCoreThreadTimeOut(allowCoreThreadTimeOut);
        // 线程执行完毕后，关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(waitForTasksToCompleteOnShutdown);
        // 线程名前缀
        executor.setThreadNamePrefix(threadNamePrefix);
        // 初始化
        executor.initialize();
        return executor;
    }

    private int getCorePoolSize(int corePoolSize){
        // 如果是-1 去机器核心数的2倍
        if(-1 == corePoolSize){
            int processors = Runtime.getRuntime().availableProcessors();
            log.info("机器核心数：{}，核心线程数：{}",processors,processors * 2);
            return processors * 2;
        }
        log.info("核心线程数：{}",corePoolSize);
        return corePoolSize;
    }

    private RejectedExecutionHandler getRejectedExecutionHandler(String rejectedExecutionHandler){
        RejectedExecutionHandler reh = null;
        try{
            log.info("配置的线程拒绝策略：{}",rejectedExecutionHandler);
            reh = (RejectedExecutionHandler) Class.forName("java.util.concurrent.ThreadPoolExecutor$" + rejectedExecutionHandler).newInstance();
        }catch (Exception e){
            log.warn("获取拒绝策略失败，默认使用 CallerRunsPolicy");
            reh = new ThreadPoolExecutor.CallerRunsPolicy();
        }
        return reh;
    }

}
